package edu.itesm.rm.scene 
{
	import flash.media.Sound;
	import flash.events.MouseEvent;
	import away3d.materials.BitmapMaterial;
	import flash.geom.Vector3D;
	import com.greensock.TweenMax;
	import away3d.containers.ObjectContainer3D;
	import away3d.containers.View3D;
	import away3d.materials.ColorMaterial;
	import away3d.primitives.Plane;
	import flash.events.Event;
	
	/**
	 * ...
	 * @author Aldo Reyes
	 */
	public class ContraScene extends View3D
	{
		
		public static const STAGE_COMPLETE:String = "stage_complete";
		public static const CAMERA_HIT:String = "camera_hit";
		
		[Embed(source="../../../../../assets/sideWall.jpg")]		
		private var sideWallTexture:Class;
		
		[Embed(source="../../../../../assets/sideWall2.jpg")]		
		private var sideWallTexture2:Class;
		
		[Embed(source="../../../../../assets/ceiling.jpg")]		
		private var ceilingTexture:Class;
		
		[Embed(source="../../../../../assets/lookup.png")]		
		private var lookupTexture:Class;
		
		[Embed(source="../../../../../assets/music.mp3")]		
		private var bgMusic:Class;
		
		private var room:ObjectContainer3D;
		private var target_holder:ObjectContainer3D;
		private var _lookup:Plane;
		private var wallWidth:Number;
		
		private static const MAX_BULLETS:int = 3;
		private var currentBullet:int = 0;
		private var origin:Vector3D = new Vector3D();
		private var bullets:Array = new Array();
		private var _enabled:Boolean;
		//private var bullets : Vector.<Bullet> = new Vector.<Bullet>();
		
		public function set enabled(value:Boolean):void 
		{
			_enabled = value;
		}
		
		public function ContraScene() 
		{
			wallWidth = 500;
		}
		
		public function init():void 
		{
			_enabled = true;
			
			room = new ObjectContainer3D();
			this.scene.addChild(room);
			
			var wallMaterial:BitmapMaterial = new BitmapMaterial(new sideWallTexture().bitmapData);
			wallMaterial.mipmap = false;
			var halfWall:Number = wallWidth>>1;
			
			var leftWall:Plane = new Plane(wallMaterial, wallWidth, halfWall);
			leftWall.rotationY = -90;
			leftWall.x = -halfWall;
			room.addChild(leftWall);
			
			wallMaterial = new BitmapMaterial(new sideWallTexture2().bitmapData);
			wallMaterial.mipmap = false;
			
			var rightWall:Plane = new Plane(wallMaterial, wallWidth, halfWall);
			rightWall.rotationY = 90;
			rightWall.x = halfWall;
			room.addChild(rightWall);
			
			var ceilingMaterial:BitmapMaterial = new BitmapMaterial(new ceilingTexture().bitmapData);
			ceilingMaterial.mipmap = false;
			
			var ceiling:Plane = new Plane(ceilingMaterial,wallWidth,wallWidth);
			ceiling.rotationX = 90;
			ceiling.y = halfWall>>1;		
			room.addChild(ceiling);
			
			var floor:Plane = new Plane(new ColorMaterial(0x700d03), wallWidth, wallWidth);
			floor.rotationX = -90;
			floor.y = -halfWall>>1;
			floor.z = ceiling.z = rightWall.z = leftWall.z -= 100;
			room.addChild(floor);
			
			var backWall:Plane = new Plane(new ColorMaterial(0x033c00), wallWidth,halfWall);
			backWall.z = halfWall-100;
			room.addChild(backWall);
			
			var lookupMaterial:BitmapMaterial = new BitmapMaterial(new lookupTexture().bitmapData);
			lookupMaterial.transparent = true;
			_lookup = new Plane(lookupMaterial, 50, 50);
			_lookup.z = backWall.z - 3;
			this.scene.addChild(_lookup);
			
			target_holder = new ObjectContainer3D();
			target_holder.addEventListener(WallTarget.DESTROYED, handleTargetDestroyed, false, 0, true);
			target_holder.addEventListener(Bullet.HIT, handleBulletEnemyHit, false, 0, true);
			target_holder.z = backWall.z -1;
			this.scene.addChild(target_holder);
			
			for (var i : int = 0; i < MAX_BULLETS; i++) {
				var bullet:Bullet = new Bullet(-halfWall, target_holder.z-1);
				bullet.addEventListener(Bullet.HIT, handleBulletHit,false,0,true);
				bullets.push(scene.addChild(bullet));
			}
			
			new bgMusic().play(0, 1000);
			
			this.stage.addEventListener(MouseEvent.CLICK, handleMouseEvents);
			this.addEventListener(Event.ENTER_FRAME, handleEnterFrame);
		}
		
		public function updateCamera(xPercentage:Number, yPercentage:Number):void{
			TweenMax.killTweensOf(camera);
			TweenMax.to(camera, .5, { x:(xPercentage-.5)*wallWidth, y:(yPercentage-.5)*wallWidth>>1, onUpdate:handleCameraUpdate} );
		}
		
		/**********************************
		*Event Handlers
		**********************************/
		private function handleCameraUpdate():void {
			trace("handleCameraUpdate");
			_lookup.x = camera.x;
			_lookup.y = camera.y;
			camera.lookAt(origin);
		}
		
		private function handleTargetDestroyed(event:Event):void{
			event.stopImmediatePropagation();
			for (var i : int = 0; i < target_holder.numChildren; i++) {
				var target:WallTarget = target_holder.getChildAt(i) as WallTarget;
				if(target && !target.destroyed){
					return;
				}
			}
			
			dispatchEvent(new Event(STAGE_COMPLETE));
		}
		
		private function handleBulletEnemyHit(event:Event):void {
			
			if (!_enabled) {
				return;
			}
			
			var bullet:ObjectContainer3D = ObjectContainer3D(event.target);
			if (Math.sqrt(Math.pow(bullet.x - camera.x, 2) + Math.pow(bullet.y - camera.y, 2)) < 40) {
				dispatchEvent(new Event(CAMERA_HIT));
			}			
		}
		
		private function handleBulletHit(event:Event):void{
			var bullet:Bullet = Bullet(event.target);
			var numTargets:int = target_holder.numChildren;
			var target:WallTarget;
			var distanceX:Number;
			var distanceY:Number;

			for (var i : int = 0; i < numTargets; i++) {
				target = target_holder.getChildAt(i) as WallTarget;
				if(target && !target.destroyed){
					distanceX = Math.abs(target.x - bullet.x);
					distanceY = Math.abs(target.y - bullet.y);
					if(distanceX <= WallTarget.TARGET_HALF_WIDTH && distanceY <= WallTarget.TARGET_HALF_WIDTH){
						target.hit();
						break;
					}
				}
			}
			
			
		}
		
		private function handleMouseEvents(event:MouseEvent):void {
			if (!_enabled) {
				return;
			}
			var bullet:Bullet = Bullet(bullets[currentBullet]); 
			if(bullet.ready){
				bullet.shoot(camera.x, camera.y);
				currentBullet = (currentBullet+1) % bullets.length;
			}
		}
		
		private function handleEnterFrame(event:Event):void 
		{
			this.render();
		}
		
		public function setStage(stage:XML):void{
			while (target_holder.numChildren > 0) {
				var target:WallTarget = target_holder.getChildAt(0) as WallTarget;
				
				if (target) {
					WallTarget(target).destroy();
					target_holder.removeChild(target);
				}
				
			}
			
			var targets:XMLList = stage.target;
			for (var i : int = 0; i < targets.length(); i++) {
				var targetXML:XML = targets[i];
				var tgt:WallTarget = new WallTarget(int(targetXML.@type), targetXML.@delay, targetXML.@frequency);
				tgt.x = targetXML.@x;
				tgt.y = targetXML.@y;
				target_holder.addChild(tgt);
				tgt.init(camera.z);
			}
		}
	}

}